class WxRequest {

  //url表示请求的接口，data表示query的参数，method表示请求的方法，config表示需要覆盖的默认参数
  get(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: "GET"
    }, config))
  }
  // 封装 POST 实例方法
  post(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: 'POST'
    }, config))
  }
  // 封装 PUT 实例方法
  put(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: 'PUT'
    }, config))
  }
  // 封装 DELETE 实例方法
  delete(url, data = {}, config = {}) {
    return this.request(Object.assign({
      url,
      data,
      method: 'DELETE'
    }, config))
  }

  // 定义默认拦截器
  interceptors = {
    // 请求拦截器
    request: (config) => config,
    // 响应拦截器
    response: (response) => response
  }

  // 全局异步处理
  all(...promise) {
    return Promise.all(promise)
  }

  // 默认参数对象
  defaults = {
    baseURL: '', // 请求基准地址
    url: '', // 开发者服务器接口地址
    data: null, // 请求参数
    method: 'GET', // 默认请求方法
    header: { // 请求头
      'Content-type': 'application/json' // 设置数据的交互格式
    },
    timeout: 60000, // 小程序默认超时时间是 60000，一分钟,
    isLoading: true // 是否显示 loading 提示框
  }
  // 定义 constructor 构造函数，用于创建和初始化类的属性和方法
  constructor(params = {}) {
    // 在实例化时传入的参数能够被 constructor 进行接收
    console.log(params)
    // 使用 Object.assign 合并默认参数以及传递的请求参数
    this.defaults = Object.assign({}, this.defaults, params)
    // 初始化数组
    this.queue = []
  }

  /**
   * @description 发起请求的方法
   * @param { Object} options 请求配置选项，同 wx.request 请求配置选项
   * @returns Promise
   */
  request(options) {
    // 拼接完整的请求地址
    options.url = this.defaults.baseURL + options.url
    // 合并请求参数
    options = {
      ...this.defaults,
      ...options
    }
    // 服务器发送之前调用请求拦截器
    options = this.interceptors.request(options)
    if (options.isLoading) {
      // 发送请求之前添加 loding
      this.queue.length === 0 && wx.showLoading()
      // 然后想队列中添加 request 标识，代表需要发送一次新请求
      this.queue.push('request')
    }
    // 使用 Promise 封装异步请求
    return new Promise((resolve, reject) => {
      // 使用 wx.request 发起请求
      wx.request({
        ...options,
        // 接口调用成功的回调函数
        success: (res) => {
          // 合并请求参数和响应参数，方便调试
          const mergrRes = Object.assign({}, res, { config: options, isSuccess: true });
          // 响应后调用响应拦截器
          resolve(this.interceptors.response(mergrRes))
        },
        // 接口调用失败的回调函数
        fail: (err) => {
          // 合并请求参数和响应参数，方便调试
          const mergrErr = Object.assign({}, err, { config: options, isSuccess: false });
          // 响应后调用响应拦截器
          reject(this.interceptors.response(mergrErr))
        },
        complete: () => {
          // 如果不展示，则直接返回
          if (!options.isLoading) return
          // 每次请求结束后，从队列中删除一个请求标识
          this.queue.pop()
          // 如果队列已经清空，在往队列中添加一个标识
          this.queue.length === 0 && this.queue.push('request')
          // 等所有的任务执行完以后，经过 100 毫秒
          // 将最后一个 request 清除，然后隐藏 loading
          this.timerId = setTimeout(() => {
            this.queue.pop()
            this.queue.length === 0 && wx.hideLoading()
          }, 100)
        }
      })
    })
  }
}
// 将 WxRequest 的实例通过模块化的方式暴露出去
export default WxRequest